// Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: listener code decoupling
// feature: develop dispatcher
// feature: support config log level by cmd tool
// feature: add statictic lookup
// ------------------------------------------------------------------

#ifndef LOOKUP_REQUEST_LISTENER_HPP_
#define LOOKUP_REQUEST_LISTENER_HPP_
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
#include <ertps/rtps/reader/ReaderListener.h>
#include <history/WriterListener.h>
#include <edds/dds/builtin/lookup/common/LookupTypes.hpp>
#include <ertps/types/TypeObjectFactory.h>
#include <functional>
using evbs::ertps::types::TypeObjectFactory;
namespace evbs {
namespace ertps {
namespace rtps {

class RTPSReader;

}  // namespace rtps
}  // namespace ertps
using vbs::common::CacheChange_t;
namespace edds {
namespace dds {
namespace builtin {

class LookupManager;

/**
 * Class LookupRequestListener that receives the lookup request messages of remote
 * endpoints.
 * @ingroup TYPES_MODULE
 */
class LookupRequestListener : public vbs::common::ReaderListener, public vbs::common::WriterListener {
 public:
    /**
     * @brief Constructor
     * @param pwlp Pointer to the writer liveliness protocol
     */
    LookupRequestListener(LookupManager* pwlp);

    /**
     * @brief Destructor
     */
    ~LookupRequestListener() override;

    /**
     * @brief Method call when this class is notified of a new cache change
     * @param reader The reader receiving the cache change
     * @param change The cache change
     */
    void onNewCacheChangeAdded(vbs::dispatcher::SubstrateReader* const sub_reader,
                               const vbs::common::CacheChange_t* const change) override;

    void onWriterChangeReceivedByAll(vbs::dispatcher::SubstrateWriter* const writer,
                                     vbs::common::CacheChange_t* change) override;

    using GetRWInfoFuncPtr = std::function<builtin::StatisticWrtierReaderInfos()>;
    void RegisterHook_get_writer_reader_infos(GetRWInfoFuncPtr func) {
        get_writer_reader_infos_funcptr = std::move(func);
    }

    using GetRemoteGuids = std::function<builtin::StatisticMatchGuids(const ertps::rtps::GUID_t& guid)>;
    void RegisterHook_get_remote_guids(GetRemoteGuids func) { get_remote_guids_funcptr = std::move(func); }

    using GetStatisticSendInfo =
        std::function<vbsutil::elog::ReturnCode_t(const ertps::rtps::GUID_t& guid, builtin::StatisticSendInfo* info)>;
    void RegisterHook_get_statistic_send_info(GetStatisticSendInfo func) {
        get_statistic_send_info_funcptr = std::move(func);
    }

    using GetStatisticRecvInfo =
        std::function<vbsutil::elog::ReturnCode_t(const ertps::rtps::GUID_t& guid, builtin::StatisticRecvInfo* info)>;
    void RegisterHook_get_statistic_recv_info(GetStatisticRecvInfo func) {
        get_statistic_recv_info_funcptr = std::move(func);
    }

    using GetStatisticWRQos = std::function<vbsutil::elog::ReturnCode_t(const ertps::rtps::GUID_t& guid,
                                                                        builtin::StatisticWriterReaderQos* qos)>;
    void RegisterHook_get_statistic_writer_reader_qos(GetStatisticWRQos func) {
        get_statistic_writer_reader_qos_funcptr = std::move(func);
    }

    using GetStatisticProxyInfos = std::function<builtin::StatisticProxyInfos(const ertps::rtps::GUID_t& guid)>;
    void RegisterHook_get_statistic_writer_reader_proxy_infos(GetStatisticProxyInfos func) {
        get_statistic_writer_reader_proxy_infos_funcptr = std::move(func);
    }

 private:
    void getWriterReaderInfo(Lookup_Request& request);
    void getMatchGuids(Lookup_Request& request);
    void getProxyInfos(Lookup_Request& request);
    void getSendInfo(Lookup_Request& request);
    void getRecvInfo(Lookup_Request& request);
    void getWriterQos(Lookup_Request& request);
    void getMessageBrief(Lookup_Request& request);
    void getTypes(Lookup_Request& request);
    void getDependencies(Lookup_Request& request);
    void remoteConfig(Lookup_Request& request);
    void getDServerInfo(Lookup_Request& request);

    //! A pointer to the lookup manager
    LookupManager* tlm_;

    //! A pointer to the TypeObject factory.
    TypeObjectFactory* factory_;

    GetRWInfoFuncPtr get_writer_reader_infos_funcptr;
    GetRemoteGuids get_remote_guids_funcptr;
    GetStatisticSendInfo get_statistic_send_info_funcptr;
    GetStatisticRecvInfo get_statistic_recv_info_funcptr;
    GetStatisticWRQos get_statistic_writer_reader_qos_funcptr;
    GetStatisticProxyInfos get_statistic_writer_reader_proxy_infos_funcptr;
};

} /* namespace builtin */
} /* namespace dds */
} /* namespace edds */
} /* namespace evbs */
#endif
#endif /* LOOKUP_REQUEST_LISTENER_HPP_*/
